package com.wish233.proxy;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.wish233.application.RpcApplication;
import com.wish233.config.RegistryConfig;
import com.wish233.config.RpcConfig;
import com.wish233.constant.RpcConstant;
import com.wish233.register.Registry;
import com.wish233.model.register.ServiceMetaInfo;
import com.wish233.register.factory.RegistryFactory;
import com.wish233.model.rpc.RpcRequest;
import com.wish233.model.rpc.RpcResponse;
import com.wish233.serializer.Serializer;
import com.wish233.serializer.factory.SerializerFactory;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 服务代理（jdk动态代理）
 * HTTP 协议
 *
 * @author WHH
 */
public class ServiceProxy implements InvocationHandler {
    private final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());
    private final RpcConfig rpcConfig = RpcApplication.getRpcConfig();

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用http请求
        //构造请求体
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setServiceName(method.getDeclaringClass().getName());
        rpcRequest.setMethodName(method.getName());
        rpcRequest.setParameterTypes(method.getParameterTypes());
        rpcRequest.setArgs(args);
        //序列化发请求
        //从注册中心获取请求地址
        RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
        Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
        ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();
        serviceMetaInfo.setServiceName(rpcRequest.getServiceName());
        serviceMetaInfo.setServiceVersion(RpcConstant.DEFAULT_SERVICE_VERSION);
        List<ServiceMetaInfo> serviceMetaInfos = registry.serviceDiscovery(serviceMetaInfo.getServiceKey());
        if (CollectionUtil.isEmpty(serviceMetaInfos)) {
            throw new RuntimeException("暂无服务");
        }
        //后续优化
        ServiceMetaInfo info = serviceMetaInfos.get(0);
        byte[] bodyBytes = serializer.serialize(rpcRequest);
        try (HttpResponse httpResponse = HttpRequest
                .post(info.getServiceAddress())
                .body(bodyBytes)
                .execute()) {
            byte[] result = httpResponse.bodyBytes();
            RpcResponse response = serializer.deserialize(result, RpcResponse.class);
            return response.getData();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //反序 列化返回响应
        return null;
    }
}
